{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 从Day15开始学习python-cookbook啦 \n",
    "- 这本书主要是教我们用一些高质量的代码去解决一些特定类型的问题 还是非常值得学习的\n",
    "- https://python3-cookbook.readthedocs.io/zh_CN/latest/index.html\n",
    "\n",
    "\n",
    "1. 将序列分解为单独的变量\n",
    "2. 解压可迭代对象赋值给多个变量\n",
    "3. 保留最后N个元素\n",
    "4. 查找最大或最小的N个元素\n",
    "5. 实现一个优先级队列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# coding:utf-8\n",
    "\n",
    "# Author: zkywsg\n",
    "# Date: 2020-06-24"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1.将序列分解成单独变量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 可迭代对象都可以通过简单的赋值变成单独变量\n",
    "# -------------------------------------------\n",
    "# 集合\n",
    "p = (4,5)\n",
    "# 拆分\n",
    "x,y = p\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'zkywsg'"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 列表拆分\n",
    "# ----------------------------------------------\n",
    "p = ['zkywsg',177,66.3,(1999,6,24)]\n",
    "name,tail,kg,birth = p\n",
    "name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1999, 6, 24)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "birth"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'zkywsg'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "name,tail,kg,(year,mon,day) = p\n",
    "name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(1999, 6, 24)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "year,mon,day"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('h', 'l')"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 其他可迭代对象\n",
    "# -------------------\n",
    "\n",
    "s = 'hello'\n",
    "a,b,c,d,e = s\n",
    "a,d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "177"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 只解压其中一部分\n",
    "data = ['zkywsg',177,66.3,(1999,6,24)]\n",
    "_,tail,_,birth = data\n",
    "tail"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "------------------------------------------------------------------------------------------------------"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.解压可迭代对象对象赋值给多个变量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['a', 'b', 'c']\n",
      "me\n"
     ]
    }
   ],
   "source": [
    "# 可迭代元素比变量多，怎么解压这些可迭代对象呢\n",
    "# 用星号表达式就可以解决这个问题\n",
    "# 比如在列表或者集合中\n",
    "\n",
    "# 比如有些人智商不正常，只有最后一个是正常的，怎么把他们分开吗\n",
    "*sb,normal = ['a','b','c','me']\n",
    "print(sb)\n",
    "print(normal)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'me'"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 比如在一群脑瘫中找到个正常的我呢（字符串）\n",
    "name = 'a,b,me,c'\n",
    "*sb,normal,sb2 = name.split(',')\n",
    "normal"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "----------------------------------------------------------------------------------\n",
    "### 3.保留最后N个元素"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([1, 2, 3])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 想想看要是有个固定大小的队列 那不是最新的几个元素就能一直保留着了吗\n",
    "# collections的deque模块就可以生成一个固定大小的队列\n",
    "# 比如现在在训练模型，我只想保留迭代到最新的模型\n",
    "from collections import deque \n",
    "\n",
    "checkpoint = deque(maxlen=3)\n",
    "checkpoint.append(1)\n",
    "checkpoint.append(2)\n",
    "checkpoint.append(3)\n",
    "checkpoint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([2, 3, 4])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "checkpoint.append(4)\n",
    "checkpoint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([3, 4, 5])"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "checkpoint.append(5)\n",
    "checkpoint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([4, 3, 4])"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "checkpoint.appendleft(4)\n",
    "checkpoint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([1, 2])"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 更一般就是灵活的队列\n",
    "# 队列比列表的好处就是时间复杂度才O(1)\n",
    "q = deque()\n",
    "q.append(1)\n",
    "q.append(2)\n",
    "q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([3, 1, 2])"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "q.appendleft(3)\n",
    "q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([3, 1])"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "q.pop()\n",
    "q"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "deque([1])"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "q.popleft()\n",
    "q"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "--------------------------------------\n",
    "### 4.查看最大或者最小的N个元素"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2000, 1000, 300]\n",
      "[40, 50, 100]\n"
     ]
    }
   ],
   "source": [
    "# 要怎么看一个集合里最大最小的呢\n",
    "# 用heapq的nlargest和nsmallest\n",
    "# 比如你要看最近6个月你欠的钱最多和最少的时候\n",
    "import heapq\n",
    "\n",
    "money = [100,200,50,300,1000,40,2000]\n",
    "print(heapq.nlargest(3,money))\n",
    "print(heapq.nsmallest(3,money))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[40, 200, 50, 300, 1000, 100, 2000]"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 这个做了什么呢？转换成列表后进行了堆排序！\n",
    "a = [100,200,50,300,1000,40,2000]\n",
    "heap = list(a)\n",
    "heapq.heapify(heap)\n",
    "heap"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "40"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "heapq.heappop(heap)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "50"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "heapq.heappop(heap)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "-----------------------------------------------------------------\n",
    "### 5.实现一个优先级队列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 有的时候嘛 比如我是vip我就是可以排的快 优先级比较高嘛 \n",
    "# 那么钥匙有个优先级队列，就可以pop出优先级最高的元素那不是很重要吗\n",
    "\n",
    "import heapq\n",
    "\n",
    "class PriorityQueue:\n",
    "    def __init__(self):\n",
    "        self._queue = []\n",
    "        self._index = 0\n",
    "        \n",
    "    def push(self,item,priority):\n",
    "        # 负数的话 就是从高到低排序的！\n",
    "        # index是保证优先级相同的时候，得按照插入顺序吧\n",
    "        heapq.heappush(self._queue,(-priority,self._index,item))\n",
    "        self._index += 1\n",
    "    \n",
    "    def pop(self):\n",
    "        return heapq.heappop(self._queue)[-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Item('me')"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "class Item:\n",
    "    def __init__(self,name):\n",
    "        self.name = name\n",
    "    def __repr__(self):\n",
    "        return 'Item({!r})'.format(self.name)\n",
    "    \n",
    "q = PriorityQueue()\n",
    "q.push(Item('a'),1)\n",
    "q.push(Item('me'),4)\n",
    "q.push(Item('b'),2)\n",
    "q.push(Item('c'),3)\n",
    "q.pop()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True True\n"
     ]
    }
   ],
   "source": [
    "# 来看看排序的记住  (priority,index,item)\n",
    "a = (1,0,Item('a'))\n",
    "b = (5,1,Item('b'))\n",
    "c = (1,2,Item('c'))\n",
    "print(a<b,a<c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
